
--[[
1服务的入口文件
2用户信息的服务
3在这个服务中可以拓展出玩家的各种功能
]]



local skynet = require("skynet")

local xxtea = require("libxxtea")

---------------------------------------------------------
-- class
---------------------------------------------------------
local Service = class("Agent")

function Service:ctor()
    local server_config = g.getServerConf()
    local proto_cfg = server_config.proto
    g.codec = new("network.proto.codec", proto_cfg)
    g.handler = new("agent.handler")
    g.user = new("agent.user")
    g.check_msg = new("agent.check_msg")
    --g.lormfactory = new("lormfactory")
    self.close = false
    self.session = -1000 --包的序号id,客户端会不断累加

    self:register()
    self:clientMessage() --接收窗户端消息

end

function Service:register()
    g.register('start', handler(self, self.onStart))
    g.register('close', handler(self, self.onClose))

end

--客户端消息处理
function Service:clientMessage()
    local msg_unpack_err = false --消息协议出错了，把连接关闭
    --解包
    local function unpack(msg, sz)
        if type(msg) ~= 'string' then
            msg = skynet.tostring(msg, sz)
        end
        if not g.uid or not g.jiami then
            --登录协议的解密
            msg = xxtea.decrypt(msg, string.len(msg), g.const.login_xxtea_key)
        else
            msg = xxtea.decrypt(msg, string.len(msg), g.jiami)
        end
        local ok, res = pcall(g.codec.unpack_message, g.codec, msg, sz)
        if not ok then
            --g.log:err("clientMessage unpack err: ", res, msg, sz)
            return
        end
        return res
    end
    --派发消息
    local function dispatch(_, _, msg, ...)
        if self.close then
            return
        end
        if msg == nil then
            if msg_unpack_err then return end
            msg_unpack_err = true
            --print("msg is nil...............")
            g.log:err("unpack_err:", g.jiami)
            --解析错误，把连接关闭
            g.call(".watchdog.service", "kick_user", g.uid, g.error_code.unpack_err)
            return
        end
        if msg.session < self.session then
            --客户端的包序号比现在的小，说明可能是截包的
            print("msg err:", msg, self.session)
            return
        end
        self.session = msg.session
        --g.log:info("msg dispatch: ", msg, ...)
        local ok , res = xpcall(g.dispatch.dispatchMessage, g.handle_err, g.dispatch, nil, nil, msg.cmd, msg.args, ...)
        if ok then
            if res and type(res) == "table" and next(res) then
                --response
                if res.code and res.code > 0 and not res.msg then
                    res.msg = g.error_code:getDes(res.code)
                end
                local message = {
                    type = 2,
                    cmd = msg.cmd,
                    args = res,
                    session = msg.session,
                    --ud = 0,--
                }
                if message.cmd ~= "C2_GS_heartbeat" then
                    --g.log:info("msg send: ", message)
                end
                local data = g.codec:cl_pack_message(message)
                local data_len = string.len(data)
                if message.cmd == "C2_GS_login" then
                    data = xxtea.encrypt(data, data_len, g.const.login_xxtea_key)
                elseif g.jiami then
                    data = xxtea.encrypt(data, data_len, g.jiami)
                end
                g.send(".watchdog.service", "send_user", g.conn_info.fd, data, g.uid, message.cmd)
            elseif not res then
                g.log:info("agent dispatchMessage res is nil ", msg, res)
            else
                g.log:err("agent dispatchMessage err ", msg, res)
            end
        else
            --客户端消息处理错误
            g.log:err("agent dispatchMessage err ", msg, res)
        end
    end
    --注册client消息
    skynet.register_protocol( {
        name = "client",
        id = skynet.PTYPE_CLIENT,
        unpack = unpack,
        dispatch = dispatch,
    })
end

--conn_info 连接的信息
function Service:onStart(conn_info)
    g.log:info("onStart agent", conn_info)
    g.conn_info = conn_info

    return true
end

function Service:onClose()
    g.log:info("agent onClose", g.uid, g.conn_info.fd)
    self.close = true
    if g.handler then
        g.handler:onClose()
    end
    if g.uid then
        --离线
        g.sendGames("disconnect", { uid = g.uid, agent = g.conn_info.agent})
    end
    g.jiami = nil --清掉加密码协议状态
    return true
end

function Service:s2cTest()
    local message = {
        type = 1,
        cmd = "s2c_test",
        args = { id=12341 },
        session = 1,
        --ud = 0,--
    }
    g.log:info("msg send s2cTest: ", message)
    local msg = codec:pack_message(message)
    g.send(".watchdog.service", "send_user", g.conn_info.fd, msg)
end

return Service